package com.h4313.ghome.ui;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;

import com.google.android.gcm.GCMRegistrar;
import com.h4313.ghome.GHomeApplication;
import com.h4313.ghome.R;
import com.h4313.ghome.io.ModulesTask;
import com.h4313.ghome.io.ModulesTask.ModulesCallback;
import com.h4313.ghome.io.ServerUtilities;
import com.h4313.ghome.model.Module;
import com.h4313.ghome.ui.fragments.ModuleFragment;
import com.h4313.ghome.ui.fragments.Refreshable;

public class HomeActivity extends Activity implements ModulesCallback {

	public static final String TAG = HomeActivity.class.getSimpleName();

	// // Refreshable mTemperature;
	// protected Refreshable mMorningConf, mTemperature;
	private AsyncTask<Void, Void, Void> mRegisterTask;
	private List<WeakReference<Refreshable>> mModulesRefreshable = new ArrayList<WeakReference<Refreshable>>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		if (GHomeApplication.DEBUG_MODE) {
			// GCMRegistrar.checkDevice(this);
			// GCMRegistrar.checkManifest(this);
		}

		setContentView(R.layout.activity_home);

		final String regId = GCMRegistrar.getRegistrationId(this);
		if (regId.equals("")) {
			GCMRegistrar.register(this, GHomeApplication.SENDER_ID);
		} else {
			if (GCMRegistrar.isRegisteredOnServer(this)) {
				// Skips registration.
			} else {
				// Try to register again, but not in the UI thread.
				// It's also necessary to cancel the thread onDestroy(),
				// hence the use of AsyncTask instead of a raw thread.
				final Context context = this;
				mRegisterTask = new AsyncTask<Void, Void, Void>() {

					@Override
					protected Void doInBackground(Void... params) {
						boolean registered = ServerUtilities.register(context,
								regId);
						// At this point all attempts to register with the app
						// server failed, so we need to unregister the device
						// from GCM - the app will try to register again when
						// it is restarted. Note that GCM will send an
						// unregistered callback upon completion, but
						// GCMIntentService.onUnregistered() will ignore it.
						if (!registered) {
							GCMRegistrar.unregister(context);
						}
						return null;
					}

					@Override
					protected void onPostExecute(Void result) {
						mRegisterTask = null;
					}

				};
				mRegisterTask.execute(null, null, null);
			}
		}

		// mTemperature = (Refreshable) getFragmentManager().findFragmentById(
		// R.id.frag_temperature);
		// final FragmentManager mManager = getFragmentManager();
		// mMorningConf = (Refreshable) mManager
		// .findFragmentById(R.id.frag_morning_conf);
	}

	private boolean mModulesLaunched = false;

	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();

		if (!mModulesLaunched) {
			ModulesTask modulesTask = new ModulesTask(this);
			modulesTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
					GHomeApplication.SERVER_URL + "/modules");
			mModulesLaunched = true;
		}
	}
	
	@Override
	public void onAllModulesFound(List<Module> modules) {
		// instanciate one fragment per module
		FragmentTransaction ft = getFragmentManager()
				.beginTransaction();
		for (Module m : modules) {
			ModuleFragment frag = ModuleFragment
					.instanciate(m.getType(), m.getId());

			if (frag != null) {
				addFragment(ft, frag);
			} else {
				Log.e(TAG,
						"Cannot create a fragment with the factory");
			}
		}
		ft.commit();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_home, menu);
		// keyboard(s) are displayed only when we click on the edit text
		getWindow().setSoftInputMode(
				WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == R.id.menu_refresh) {
			refreshAll();
			return true;
		} else {
			return super.onOptionsItemSelected(item);
		}
	}

	public void newModule(View view) {
		Intent intent = new Intent(this, NewModuleActivity.class);
		this.startActivityForResult(intent, 1);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == 1 && resultCode == RESULT_OK) {

			String moduleName = data
					.getStringExtra(NewModuleActivity.RESULT_MODULE_NAME);
			Integer id = data.getIntExtra(NewModuleActivity.RESULT_MODULE_ID,
					-1);

			ModuleFragment frag = ModuleFragment.instanciate(moduleName, id);
			frag.setNeedToBeInFirst(true);
			if (frag != null) {
				FragmentTransaction tx = getFragmentManager()
						.beginTransaction();
				tx.setCustomAnimations(R.animator.new_module,
						R.animator.new_module);

				addFragment(tx, frag);

				tx.commit();
			} else {
				Log.e(TAG, "Cannot create a fragment with the factory");
			}
		} else {
			super.onActivityResult(requestCode, resultCode, data);
		}
	}

	private void addFragment(FragmentTransaction tx, ModuleFragment fragment) {
		tx.add(R.id.container_modules, fragment, fragment.getModuleName() + "_"
				+ fragment.getModuleId());

		if (fragment instanceof Refreshable) {
			mModulesRefreshable.add(new WeakReference<Refreshable>(
					(Refreshable) fragment));
		}
	}

	private void refreshAll() {
		for (WeakReference<Refreshable> frag : mModulesRefreshable) {
			if (frag.get() != null) {
				frag.get().refresh();
			}
		}
		// mTemperature.refresh();
		// mMorningConf.refresh();
	}

	@Override
	protected void onDestroy() {
		if (mRegisterTask != null) {
			mRegisterTask.cancel(true);
		}
		// GCMRegistrar.onDestroy(this);
		super.onDestroy();
	}
}
